package com.kx.center.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.lang3.StringUtils;

public class MeiTuanUtil {

	public static String signRequest(String serverUrl,
			Map<String, String> params, String app_id, String appSecret,
			long timestamp) {
		List<NameValuePair> nameValueParams = new ArrayList<NameValuePair>();
		nameValueParams.add(new NameValuePair("app_id", app_id));
		if (params != null && !params.isEmpty()) {
			for (String paramName : params.keySet()) {
				nameValueParams.add(new NameValuePair(paramName, params
						.get(paramName)));
			}
		}
		String paramForSig = getSortedParam(nameValueParams, timestamp);
		return signRequest(serverUrl, paramForSig, appSecret);
	}

	/**
	 * 获取签名
	 * @param serverUrl
	 *            请求url（必填）
	 * @param paramContent
	 *            已排序的参数内容（必填）
	 * @param appSecret
	 *            应用密钥（必填）
	 * @return
	 */
	public static String signRequest(String serverUrl, String paramContent,
			String appSecret) {
		return localMD5(serverUrl + "?" + paramContent + appSecret);
	}

	/**
	 * 针对参数排序
	 * @param params
	 *            参数集合
	 * @param timestamp
	 *            时间戳
	 * @return
	 */
	private static String getSortedParam(List<NameValuePair> params,
			long timestamp) {
		List<String> keyList = new ArrayList<String>();
		params.add(new NameValuePair("timestamp", timestamp + ""));
		Collections.sort(params, new Comparator<NameValuePair>() {
			public int compare(NameValuePair nameValuePair1,
					NameValuePair nameValuePair2) {
				return nameValuePair1.getName().compareTo(
						nameValuePair2.getName());
			}
		});
		for (int i = 0; i < params.size(); i++) {
			String value = params.get(i).getValue() == null ? "" : params
					.get(i).getValue();
			String keyValue = params.get(i).getName() + "=" + value;
			keyList.add(keyValue);
		}
		return StringUtils.join(keyList, "&");
	}

	/**
	 * 使用MD5加密
	 * @param src
	 * @return
	 */
	private static String localMD5(String src) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return byte2hex(md.digest(src.getBytes()));
	}

	/**
	 * 二进制转化为大写的十六进制
	 * 
	 * @param b
	 * @return
	 */
	private static String byte2hex(byte[] b) {
		StringBuffer buf = new StringBuffer();
		int i;

		for (int offset = 0; offset < b.length; offset++) {
			i = b[offset];
			if (i < 0)
				i += 256;
			if (i < 16)
				buf.append("0");
			buf.append(Integer.toHexString(i));
		}
		return buf.toString();
	}

	public static String concatParams(Map<String, String> params)
			throws UnsupportedEncodingException {
		Object[] key_arr = params.keySet().toArray();
		Arrays.sort(key_arr);
		String str = "";

		for (Object key : key_arr) {
			String val = params.get(key);
			str += "&" + key + "=" + val;
		}
		return str.replaceFirst("&", "");
	}

	/**
	 * 美团需要的post请求
	 * @param url
	 * @param data
	 */
	public static String post(String url, String data) throws HttpException,
			IOException {

		HttpClient httpclient = new HttpClient();
		PostMethod method = new PostMethod(url);

		StringRequestEntity requestEntity = new StringRequestEntity(data,
				"application/x-www-form-urlencoded", "UTF-8");
		method.setRequestEntity(requestEntity);

		int code = httpclient.executeMethod(method);

		byte[] responseBody = null;

		if (code == HttpStatus.SC_OK) {
			Header contentEncoding = method
					.getResponseHeader("Content-Encoding");
			if (contentEncoding != null
					&& contentEncoding.getValue().toLowerCase().indexOf("gzip") > -1) {
				InputStream is = method.getResponseBodyAsStream();
				GZIPInputStream gzip = new GZIPInputStream(is);
				byte[] buf = new byte[1024];

				int num = -1;
				ByteArrayOutputStream baos = new ByteArrayOutputStream();

				while ((num = gzip.read(buf, 0, buf.length)) != -1) {
					baos.write(buf, 0, num);
				}
				responseBody = baos.toByteArray();
				baos.flush();
				baos.close();
				gzip.close();
				is.close();
			} else {
				responseBody = method.getResponseBody();
			}

			Header contentType = method.getResponseHeader("Content-Type");
			if (contentType != null) {
				String encoding = contentType.getValue().toUpperCase();

				Pattern pattern = Pattern.compile("CHARSET=([^;]*)");
				Matcher matcher = pattern.matcher(encoding);
				String charset = matcher.find() ? matcher.group(1) : null;

				if (charset != null) {
					responseBody = (new String(responseBody, charset))
							.getBytes("UTF-8");
				}
			}
		}
		String result = new String(responseBody);
		return result;
	}

	/**
	 * 美团需要的get请求
	 * @param url
	 * @param data
	 */
	public static String get(String url, String data) throws HttpException,
			IOException {

		String curl = url + "?" + data;

		HttpClient httpclient = new HttpClient();
		GetMethod method = new GetMethod(curl);

		int code = httpclient.executeMethod(method);

		byte[] responseBody = null;

		if (code == HttpStatus.SC_OK) {
			Header contentEncoding = method
					.getResponseHeader("Content-Encoding");
			if (contentEncoding != null
					&& contentEncoding.getValue().toLowerCase().indexOf("gzip") > -1) {
				InputStream is = method.getResponseBodyAsStream();
				GZIPInputStream gzip = new GZIPInputStream(is);
				byte[] buf = new byte[1024];

				int num = -1;
				ByteArrayOutputStream baos = new ByteArrayOutputStream();

				while ((num = gzip.read(buf, 0, buf.length)) != -1) {
					baos.write(buf, 0, num);
				}
				responseBody = baos.toByteArray();
				baos.flush();
				baos.close();
				gzip.close();
				is.close();
			} else {
				responseBody = method.getResponseBody();
			}

			Header contentType = method.getResponseHeader("Content-Type");
			if (contentType != null) {
				String encoding = contentType.getValue().toUpperCase();

				Pattern pattern = Pattern.compile("CHARSET=([^;]*)");
				Matcher matcher = pattern.matcher(encoding);
				String charset = matcher.find() ? matcher.group(1) : null;

				if (charset != null) {
					responseBody = (new String(responseBody, charset))
							.getBytes("UTF-8");
				}
			}
		}
		String result = new String(responseBody);
		return result;
	}

}
